#ifndef HIGHLIGHTER_H
#define HIGHLIGHTER_H

#include "HighlightData.h"

#include "simodo/shell/access/LspStructures.h"
#include "simodo/inout/token/Token.h"

#include <QSyntaxHighlighter>
#include <QTextCharFormat>
#include <QTextBlockUserData>

#include <unordered_map>

QT_BEGIN_NAMESPACE
class QTextDocument;
class QPalette;
QT_END_NAMESPACE

class CodeEdit;

namespace simodo::variable
{
    class Object;
}

struct AnchorPosition
{
    int line = -1;
    int character = -1;
    int length = 0;
};

class Highlighter : public QSyntaxHighlighter
{
public:
    enum class ContrastMode { Normal, Hight };
    enum class SemanticFormatOrder { Early, Post};

private:
    Q_OBJECT

    HighlightData                               _highlight_data;
    const QVector<simodo::shell::Diagnostic> &  _diagnostics;
    const std::multimap<int,simodo::shell::SemanticToken> & 
                                                _semantic_tokens;

    SemanticFormatOrder                         _semantic_format_order;
    ContrastMode                                _contrast_mode = ContrastMode::Normal;

    std::unordered_map<std::u16string,QTextCharFormat>
                                                _current_formats;

    AnchorPosition                              _anchor;

public:
    Highlighter(QTextDocument * document, 
                const Highlighter * highlighter, 
                SemanticFormatOrder semantic_format_order, 
                ContrastMode contrast_mode);
    Highlighter(QTextDocument * document, 
                HighlightData highlight_data, 
                const QPalette & palette,
                const QVector<simodo::shell::Diagnostic> & diagnostics,
                const std::multimap<int,simodo::shell::SemanticToken> & semantic_tokens, 
                SemanticFormatOrder semantic_format_order);

    const HighlightData & highlight_data() const { return _highlight_data; }
    const QVector<simodo::shell::Diagnostic> & diagnostics() const { return _diagnostics; }
    const std::multimap<int,simodo::shell::SemanticToken> & semantic_tokens() const { return _semantic_tokens; }
    const std::unordered_map<std::u16string,QTextCharFormat> & current_formats() const { return _current_formats; }
    const QTextCharFormat & findFormat(const std::u16string & type) const;

    void setupCurrentFormat(const QPalette & palette);
    void setAnchorPosition(const AnchorPosition & ref) { _anchor = ref; }

protected:
    virtual void highlightBlock(const QString & text) override;

    void highlightElement(std::shared_ptr<simodo::variable::Object> object, const std::u16string & text, int pos);

private:
    void setupCurrentFormat(std::shared_ptr<simodo::variable::Object> theme);
    QTextCharFormat buildFormat(const simodo::variable::Value & fmt);
    void            formatSemanticTokens(int line);
    void            formatDiagnostic(int line);
};

#endif // HIGHLIGHTER_H
